/**
 * Notes: 问答模块业务逻辑
 * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY cclinux0730 (wechat)
 * Date: 2024-06-08 07:48:00 
 */

const BaseProjectService = require('./base_project_service.js');
const timeUtil = require('../../../framework/utils/time_util.js');
const util = require('../../../framework/utils/util.js');
const dataUtil = require('../../../framework/utils/data_util.js');
const QuestionModel = require('../model/question_model.js');
const AnswerModel = require('../model/answer_model.js');
const UserModel = require('../model/user_model.js');
const setupUtil = require('../../../framework/utils/setup/setup_util.js');

class QuestionService extends BaseProjectService {

	async getAnswerDetail(id) {
		return await AnswerModel.getOne(id);
	}

	async delAnswer(userId, id) {
		return await AnswerModel.del({ ANSWER_USER_ID: userId, _id: id });
	}

	// 得分统计
	async statAnswer(userId) { 
		let where = {
			ANSWER_USER_ID: userId,
			ANSWER_TYPE: 1
		}
		let cnt = await AnswerModel.count(where);
		let score = await AnswerModel.sum(where, 'ANSWER_SCORE');

		let data = {
			USER_ANSWER_CNT: cnt,
			USER_ANSWER_SCORE: score
		}
		await UserModel.edit({ USER_MINI_OPENID: userId }, data);
	}

	async saveMyAnswer(userId, {answers, type = 1, cateId, cateName, start, end, duration}) {
		// 参数验证
		if (!userId || !answers || !Array.isArray(answers) || answers.length === 0) {
			this.AppError('用户ID、答案不能为空');
		}

		// 计算分数
		let totalScore = 0;
		let succCnt = 0;
		answers.forEach(item => {
			if (item.status) {
				totalScore += (item.score || 1);
				succCnt ++;
			}
		})

		// 构建答题记录数据
		const data = {
			_pid: this.getProjectId(),
			ANSWER_ID: dataUtil.makeID(),
			ANSWER_USER_ID: userId,
			ANSWER_TYPE: type,
			ANSWER_CATE_ID: cateId,
			ANSWER_CATE_NAME: cateName,
			ANSWER_DAY: timeUtil.time('Y-M-D'),
			ANSWER_START: start,
			ANSWER_END: end,
			ANSWER_DURATION: duration,
			ANSWER_SCORE: totalScore,
			ANSWER_CNT: answers.length,
			ANSWER_SUCC_CNT: succCnt, 
			ANSWER_LIST: answers
		};

		// 保存答题记录
		const result = await AnswerModel.insert(data);

		// 更新用户得分统计
		await this.statAnswer(userId);

		if (type == 0) {
			const user = await UserModel.getOne({ USER_MINI_OPENID: userId });
			const praticeRecord = ((user || {}).USER_PRACTICE_RECORD || {})
			const page = praticeRecord[cateId] || 1
			praticeRecord[cateId] = page + 1;
			let data = {
				USER_PRACTICE_RECORD: praticeRecord
			}
			await UserModel.edit({ USER_MINI_OPENID: userId }, data);
		}

		return { success: true, id: result };
	}

	// 随机N条记录，生成本次题库
	async genQuestion(userId, type, cateId) {
		// 参数验证
		if (!cateId) {
			this.AppError('分类ID不能为空');
		}

		// 获取答题配置
		let setup = await setupUtil.get('answer');

		if (setup) {
			setup = dataUtil.dbForms2Obj(setup);
		}

		// 查询可用题目
		const where = {
			QUESTION_CATE_ID: String(cateId),
			QUESTION_STATUS: QuestionModel.STATUS.COMM // 只选择启用状态的题目
		};

		let questions = [];
		switch(type) {
			case 0: {
				const user = await UserModel.getOne({ USER_MINI_OPENID: userId });
				const practiceRecord = (user || {}).USER_PRACTICE_RECORD;
				const page = (practiceRecord || {})[cateId] || 1;
				const orderBy = {
					'QUESTION_ORDER': 'asc'
				};
				questions = (await QuestionModel.getList(where, '*', orderBy, page, 20, true)).list;
				break;
			}
			case 1: {
				if ((setup || {}).open != true) {
					this.AppError('竞赛尚未开始!');
				}
				let cnt = await AnswerModel.count({
					ANSWER_CATE_ID: String(cateId),
					ANSWER_USER_ID: userId,
					ANSWER_TYPE: type,
					ANSWER_DAY: timeUtil.time('Y-M-D')
				});
				if (cnt >= (setup || {}).dayCnt) {
					this.AppError('今日答题已超过次数');
				}
				questions = await QuestionModel.rand(where, '*', (Number((setup || {}).size) || 10));
				break;
			}
			default:
				break
		}

		// 格式化题目数据
		const questionList = questions.map(q => ({
			id: q._id,
			type: q.QUESTION_OBJ.type,
			title: q.QUESTION_TITLE,
			img: q.QUESTION_OBJ.img,
			optionList: q.QUESTION_FORMS.filter(i => (i.val && i.mark.indexOf('option')>-1)),
			obj: q.QUESTION_OBJ,
			score: (setup || {}).score || 1
		}));
		let maxTime = ((setup || {}).maxtime || 10) * 60;
		return { questionList, maxTime};
	}

	async getMyAnswerList(userId, {
		search, // 搜索条件
		sortType, // 搜索菜单
		sortVal, // 搜索菜单
		orderBy, // 排序 
		page,
		size,
		isTotal = true,
		oldTotal
	}) {
		orderBy = orderBy || {
			'ANSWER_ADD_TIME': 'desc'
		};
		let fields = 'ANSWER_SCORE,ANSWER_CATE_NAME,ANSWER_TYPE,ANSWER_ADD_TIME,ANSWER_CNT,ANSWER_PER,ANSWER_SUCC_CNT,ANSWER_DURATION,ANSWER_START,ANSWER_END';

		let where = {};
		where.and = {
			ANSWER_USER_ID: userId,
			_pid: this.getProjectId() //复杂的查询在此处标注PID
		};

		if (util.isDefined(search) && search) {
			where.or = [
				{ ANSWER_CATE_NAME: { $regex: search, $options: 'i' } }
			];
		} else if (sortType && util.isDefined(sortVal)) {
			// 搜索菜单
			switch (sortType) {
				case 'type': {
					where.and.ANSWER_TYPE = Number(sortVal);
					break;
				}
				case 'cateId': {
					where.and.ANSWER_CATE_ID = String(sortVal);
					break;
				}
				case 'sort': {
					// Convert sortVal to string direction
					const direction = sortVal === 'desc' ? 'desc' : 'asc';
					orderBy = { 'ANSWER_ADD_TIME': direction };
					break;
				}
			}
		}
		return await AnswerModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);
	}

	async getScoreRankList({
		search, // 搜索条件
		sortType, // 搜索菜单
		sortVal, // 搜索菜单
		orderBy, // 排序 
		page,
		size,
		isTotal = true,
		oldTotal
	}) {
		orderBy = {
			'USER_ANSWER_SCORE': 'desc'
		};
		let fields = 'USER_NAME,USER_ANSWER_SCORE';

		let where = {};
		where.and = {
			_pid: this.getProjectId() //复杂的查询在此处标注PID
		};

		if (util.isDefined(search) && search) {
			where.or = [
				{ USER_NAME: { $regex: search, $options: 'i' } }
			];
		} else if (sortType && util.isDefined(sortVal)) {
			// 搜索菜单
			switch (sortType) {
				case 'sort': {
					// Convert sortVal to string direction
					const direction = sortVal === 'desc' ? 'desc' : 'asc';
					orderBy = { 'USER_ANSWER_SCORE': direction };
					break;
				}
			}
		}
		return await UserModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);
	}
}
module.exports = QuestionService;